package com.sicheng.metadata.se.string;

import org.junit.Test;

/**
 * @author : zsc
 * @date :
 */
public class StringPool {
  public static void main(String[] args) {
    String s1 = new String("ab");//执行完以后，会在字符串常量池中会生成"ab"
    String s = new String("1");
    s.intern();//调用此方法之前，字符串常量池中已经存在了"1"
    String s2 = "1";
    System.out.println(s == s2);//jdk6：false   jdk7/8：false

        /*
         1、s3变量记录的地址为：new String("11")
         2、经过上面的分析，我们已经知道执行完pos_1的代码，在堆中有了一个new String("11")
         这样的String对象。但是在字符串常量池中没有"11"
         3、接着执行s3.intern()，在字符串常量池中生成"11"
           3-1、在JDK6的版本中，字符串常量池还在永久代，所以直接在永久代生成"11",也就有了新的地址
           3-2、而在JDK7的后续版本中，字符串常量池被移动到了堆中，此时堆里已经有new String（"11"）了
           出于节省空间的目的，直接将堆中的那个字符串的引用地址储存在字符串常量池中。没错，字符串常量池
           中存的是new String（"11"）在堆中的地址
         4、所以在JDK7后续版本中，s3和s4指向的完全是同一个地址。
         */
    String s3 = new String("1") + new String("1");//pos_1
    String intern = s3.intern();

    System.out.println(s3==intern);



    String s4 = "11";//s4变量记录的地址：使用的是上一行代码代码执行时，在常量池中生成的"11"的地址
    System.out.println(s3 == s4);//jdk6：false  jdk7/8：true

    System.out.println(new String("4444"));
  }

  @Test
  public void test1(){

    String xxxxxx = "*****";
    System.out.println(xxxxxx==xxxxxx.intern());
    String x = "ab";
    String s = new String("a") + new String("b");//new String("ab")
    //
    //在上一行代码执行完以后，字符串常量池中并没有"ab"
		/*
		1、jdk6中：在字符串常量池（此时在永久代）中创建一个字符串"ab"
        2、jdk8中：字符串常量池（此时在堆中）中没有创建字符串"ab",而是创建一个引用，指向new String("ab")，		  将此引用返回
        3、详解看上面
		*/
    String s2 = s.intern();

    System.out.println(s2 == "ab");//jdk6:true  jdk8:true
    System.out.println(s == "ab");//jdk6:false  jdk8:false
  }
}
